package convert

import (
	"fmt"
	"math"
	"strconv"
	"strings"
)

type SignedInteger interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64
}

type UnsignedInteger interface {
	~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}

type Float interface {
	~float32 | ~float64
}

// IntToStr 将有符号整数转换为字符串。
//
// 这是一个泛型函数，支持所有有符号整数类型(int, int8, int16, int32, int64)。
//
// 参数:
//   - s: 要转换的有符号整数
//
// 返回值:
//   - string: 转换后的字符串表示
//
// 示例:
//
//	str := IntToStr(42) // 返回 "42"
//	str := IntToStr(int64(-100)) // 返回 "-100"
func IntToStr[T SignedInteger](s T) string {
	return strconv.FormatInt(int64(s), 10)
}

// UintToStr 将无符号整数转换为字符串。
//
// 这是一个泛型函数，支持所有无符号整数类型(uint, uint8, uint16, uint32, uint64)。
//
// 参数:
//   - s: 要转换的无符号整数
//
// 返回值:
//   - string: 转换后的字符串表示
//
// 示例:
//
//	str := UintToStr(uint(42)) // 返回 "42"
//	str := UintToStr(uint64(100)) // 返回 "100"
func UintToStr[T UnsignedInteger](s T) string {
	return strconv.FormatUint(uint64(s), 10)
}

// FloatToStr 将浮点数转换为字符串。
//
// 这是一个泛型函数，支持所有浮点数类型(float32, float64)。
//
// 参数:
//   - f: 要转换的浮点数
//
// 返回值:
//   - string: 转换后的字符串表示
//
// 示例:
//
//	str := FloatToStr(3.14) // 返回 "3.14"
//	str := FloatToStr(float32(-0.5)) // 返回 "-0.5"
func FloatToStr[T Float](f T) string {
	return strconv.FormatFloat(float64(f), 'f', -1, 64)
}

// string to int

// Str2Int 将字符串转换为int类型。
// 如果转换失败会返回0并打印错误日志。
//
// 参数:
//   - s: 要转换的字符串
//
// 返回值:
//   - int: 转换后的整数值(转换失败返回0)
//
// 示例:
//
//	num := Str2Int("42") // 返回 42
//	num := Str2Int("abc") // 返回 0
func Str2Int(s string) int {
	res, err := strconv.Atoi(s)
	if err != nil {
		fmt.Println("Str2Int error:" + err.Error())
		res = 0
	}
	return res
}

// Str2Int8 将字符串转换为int8类型。
// 底层调用Str2Int64实现，超出int8范围的数值会被截断。
//
// 参数:
//   - s: 要转换的字符串
//
// 返回值:
//   - int8: 转换后的int8值(转换失败返回0)
//
// 示例:
//
//	num := Str2Int8("127") // 返回 127
//	num := Str2Int8("128") // 返回 -128 (溢出)
func Str2Int8(s string) int8 {
	return int8(Str2Int64(s))
}

// Str2Int16 将字符串转换为int16类型。
// 底层调用Str2Int64实现，超出int16范围的数值会被截断。
//
// 参数:
//   - s: 要转换的字符串
//
// 返回值:
//   - int16: 转换后的int16值(转换失败返回0)
//
// 示例:
//
//	num := Str2Int16("32767") // 返回 32767
//	num := Str2Int16("32768") // 返回 -32768 (溢出)
func Str2Int16(s string) int16 {
	return int16(Str2Int64(s))
}

// Str2Int32 将字符串转换为int32类型。
// 底层调用Str2Int64实现，超出int32范围的数值会被截断。
//
// 参数:
//   - s: 要转换的字符串
//
// 返回值:
//   - int32: 转换后的int32值(转换失败返回0)
//
// 示例:
//
//	num := Str2Int32("2147483647") // 返回 2147483647
//	num := Str2Int32("2147483648") // 返回 -2147483648 (溢出)
func Str2Int32(s string) int32 {
	return int32(Str2Int64(s))
}

// Str2Int64 将字符串转换为int64类型。
//
// 参数:
//   - s: 要转换的字符串
//
// 返回值:
//   - int64: 转换后的int64值(转换失败返回0)
//
// 示例:
//
//	num := Str2Int64("9223372036854775807") // 返回 9223372036854775807
//	num := Str2Int64("abc") // 返回 0
func Str2Int64(s string) int64 {
	res, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		fmt.Println("Str2Int64 error:" + err.Error())
		res = 0
	}
	return res
}

// string to uint

// Str2Uint 将字符串转换为uint类型。
// 底层调用Str2Uint64实现，超出uint范围的数值会被截断。
//
// 参数:
//   - s: 要转换的字符串
//
// 返回值:
//   - uint: 转换后的uint值(转换失败返回0)
//
// 示例:
//
//	num := Str2Uint("4294967295") // 返回 4294967295 (32位系统)
//	num := Str2Uint("-1") // 返回 0 (无效输入)
func Str2Uint(s string) uint {
	return uint(Str2Uint64(s))
}

// Str2Uint8 将字符串转换为uint8类型。
// 底层调用Str2Uint64实现，超出uint8范围的数值会被截断。
//
// 参数:
//   - s: 要转换的字符串
//
// 返回值:
//   - uint8: 转换后的uint8值(转换失败返回0)
//
// 示例:
//
//	num := Str2Uint8("255") // 返回 255
//	num := Str2Uint8("256") // 返回 0 (溢出)
func Str2Uint8(s string) uint8 {
	return uint8(Str2Uint64(s))
}

// Str2Uint16 将字符串转换为uint16类型。
// 底层调用Str2Uint64实现，超出uint16范围的数值会被截断。
//
// 参数:
//   - s: 要转换的字符串
//
// 返回值:
//   - uint16: 转换后的uint16值(转换失败返回0)
//
// 示例:
//
//	num := Str2Uint16("65535") // 返回 65535
//	num := Str2Uint16("65536") // 返回 0 (溢出)
func Str2Uint16(s string) uint16 {
	return uint16(Str2Uint64(s))
}

// Str2Uint32 将字符串转换为uint32类型。
// 底层调用Str2Uint64实现，超出uint32范围的数值会被截断。
//
// 参数:
//   - s: 要转换的字符串
//
// 返回值:
//   - uint32: 转换后的uint32值(转换失败返回0)
//
// 示例:
//
//	num := Str2Uint32("4294967295") // 返回 4294967295
//	num := Str2Uint32("4294967296") // 返回 0 (溢出)
func Str2Uint32(s string) uint32 {
	return uint32(Str2Uint64(s))
}

// Str2Uint64 将字符串转换为uint64类型。
//
// 参数:
//   - s: 要转换的字符串
//
// 返回值:
//   - uint64: 转换后的uint64值(转换失败返回0)
//
// 示例:
//
//	num := Str2Uint64("18446744073709551615") // 返回 18446744073709551615
//	num := Str2Uint64("-1") // 返回 0 (无效输入)
func Str2Uint64(s string) uint64 {
	res, err := strconv.ParseUint(s, 10, 64)
	if err != nil {
		fmt.Println("Str2Uint64 error:" + err.Error())
		res = 0
	}
	return res
}

// string to float32
// Str2Float32 将字符串转换为float32类型。
//
// 参数:
//   - s: 要转换的字符串
//
// 返回值:
//   - float32: 转换后的float32值(转换失败返回0)
//
// 示例:
//
//	num := Str2Float32("3.14") // 返回 3.14
//	num := Str2Float32("abc") // 返回 0
func Str2Float32(s string) float32 {
	return float32(Str2Float64(s))
}

// string to float64
// Str2Float64 将字符串转换为float64类型。
//
// 参数:
//   - s: 要转换的字符串
//
// 返回值:
//   - float64: 转换后的float64值(转换失败返回0)
//
// 示例:
//
//	num := Str2Float64("3.141592653589793") // 返回 3.141592653589793
//	num := Str2Float64("abc") // 返回 0
func Str2Float64(s string) float64 {
	f, err := strconv.ParseFloat(s, 64)
	if err != nil {
		panic(err)
	}
	return f
}

// Float642Int64 将浮点数转换为整数，保留指定小数位数。
// 通过乘以10的retain次方实现保留小数位数的转换。
//
// 参数:
//   - num: 要转换的浮点数
//   - retain: 要保留的小数位数
//
// 返回值:
//   - int64: 转换后的整数值
//
// 示例:
//
//	val := Float642Int64(3.14159, 2) // 返回 314
func Float642Int64(num float64, retain int) int64 {
	return int64(num * math.Pow10(retain))
}

// Int642Float64 将整数转换为浮点数，恢复指定小数位数。
// 通过除以10的retain次方实现小数位数的恢复。
//
// 参数:
//   - num: 要转换的整数值
//   - retain: 要恢复的小数位数
//
// 返回值:
//   - float64: 转换后的浮点数值
//
// 示例:
//
//	val := Int642Float64(314, 2) // 返回 3.14
func Int642Float64(num int64, retain int) float64 {
	return float64(num) / math.Pow10(retain)
}

// WrapToFloat64 将浮点数放大指定小数位数。
// 通过乘以10的retain次方实现数值放大。
//
// 参数:
//   - num: 要处理的浮点数
//   - retain: 要放大的小数位数
//
// 返回值:
//   - float64: 放大后的数值
//
// 示例:
//
//	val := WrapToFloat64(3.14, 2) // 返回 314
func WrapToFloat64(num float64, retain int) float64 {
	return num * math.Pow10(retain)
}

// UnwrapToInt64 将整数缩小指定小数位数并转换为int64。
// 先转换为浮点数再除以10的retain次方实现数值缩小。
//
// 参数:
//   - num: 要处理的整数值
//   - retain: 要缩小的小数位数
//
// 返回值:
//   - int64: 缩小后的整数值
//
// 示例:
//
//	val := UnwrapToInt64(314, 2) // 返回 3
func UnwrapToInt64(num int64, retain int) int64 {
	return int64(Int642Float64(num, retain))
}

// Bool2Str 将布尔值转换为字符串。
//
// 参数:
//   - s: 要转换的布尔值
//
// 返回值:
//   - string: "true"或"false"
//
// 示例:
//
//	str := Bool2Str(true)  // 返回 "true"
//	str := Bool2Str(false) // 返回 "false"
func Bool2Str(s bool) string {
	return strconv.FormatBool(s)
}

// UnicodeIndex 获取子串在Unicode字符串中的字符位置索引（非字节索引）。
// 正确处理多字节字符的索引计算。
//
// 参数:
//   - str: 要搜索的Unicode字符串
//   - substr: 要查找的子串
//
// 返回值:
//   - int: 子串的字符位置索引，未找到返回-1
//
// 示例:
//
//	pos := UnicodeIndex("你好世界", "世界") // 返回 2
//	pos := UnicodeIndex("hello", "x")    // 返回 -1
func UnicodeIndex(str, substr string) int {
	result := strings.Index(str, substr)
	if result >= 0 {
		prefix := []byte(str)[0:result]
		rs := []rune(string(prefix))
		result = len(rs)
	}

	return result
}
